#pragma once
#include <iostream>
using namespace std;
#include <functional>
#include <vector>
#include <unistd.h>
#include <sys/wait.h>
#include "Channel.hpp"
#include "Task.hpp"
using work_t = function<void()>;

enum 
{
    OK = 0,
    UsageError,
    PipeError,
    ForkError
};
class ProcessPool
{
public:
    ProcessPool(int n,work_t w)
    :processnum(n),work(w)
    {

    }

    int InitProcessPool()
    {
        //创建指定个数的进程
        for(int i = 0;i<processnum;i++)
        {
            //现有管道
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if(n<0)
                return PipeError;
            //创建进程
            pid_t id = fork();
            if(id<0)
                return ForkError;
            
            if(id==0)
            {
                std::cout<<getpid<<",child close history fd:";
                for(auto& c:channels)
                {
                    std::cout<<c.wFd()<<" ";
                    c.Close();
                }
                std::cout<<"over"<<std::endl;
                close(pipefd[1]);//read  关闭写端口
                
                std::cout<<"debug: "<<pipefd[0]<<std::endl;
                dup2(pipefd[0],0);
                work();
                ::exit(0);
            }
            //父进程
            ::close(pipefd[0]);//write; 关闭读端口
            channels.emplace_back(pipefd[1],id);
        }
        return OK;
    }
    void DispatchTask()
    {
        int who = 0;
        int num = 20;
        while(num--)
        {
            int task = _tm.SelectTask();

            Channel& cur = channels[who++];
            who%=channels.size();

            std::cout<<"#############"<<std::endl;
            std::cout<<"send"<<task<<"to"<<cur.Name()<<",任务还剩"<<num<<std::endl;
            std::cout<<"#############"<<std::endl;

            cur.Send(task);
            sleep(1);
        }
    }
    void CleanProcessPool()
    {
        for(auto& c:channels)
        {
            c.Close();
            pid_t rid = waitpid(c.Id(),nullptr,0);
            if(rid>0)
            {
                std::cout<<"child"<<rid<<"wait...success"<<std::endl;
            }
        }
    }
    void DebugPrint()
    {
        for (auto &c : channels)
        {
            std::cout << c.Name() << std::endl;
        }
    }
private:
    vector<Channel> channels;
    int processnum;
    work_t work;
};